package com.shiro;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.alibaba.fastjson.JSONObject;
import com.modules.system.service.SysUserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.common.constant.Codes;
import com.common.constant.Constants;
import com.common.exception.CustomException;
import com.common.util.StringUtil;
import com.modules.system.dao.SysMenuDao;
import com.modules.system.dao.SysUserDao;
import com.modules.system.entity.SysMenuEntity;
import com.modules.system.entity.SysUserEntity;


@Component
public class UserRealm  extends AuthorizingRealm {

    @Autowired
    private SysUserDao sysUserDao;
    @Autowired
    private SysMenuDao sysMenuDao;

	@Autowired
	private SysUserService sysUserService;
	
    /**
     * 授权(验证权限时调用)
     * 进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定用户的访问控制的方法 
     */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

		UserPrincipal principal = (UserPrincipal)principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		if(principal.isPermsLoad()) {
			info.setStringPermissions(principal.getPermsSet());
		}else {
			Long userId = principal.getUserId();
			List<String> permsList = null;
			
			//系统管理员，拥有最高权限
			if(userId == Constants.SUPER_ADMIN){
				List<SysMenuEntity> menuList = sysMenuDao.getListWithParent();
				permsList = new ArrayList<String>(menuList.size());
				for(SysMenuEntity menu : menuList){
					permsList.add(menu.getPerms());
				}
			}else{
				permsList = sysUserDao.getAllPerms(userId);
			}
	
			//用户权限列表
			Set<String> permsSet = new HashSet<String>();
			for(String perms : permsList){
				if(StringUtil.isNullString(perms)){
					continue;
				}
				permsSet.addAll(Arrays.asList(perms.trim().split(",")));
			}
			
			info.setStringPermissions(permsSet);
			principal.setPermsLoad(true);
			principal.setPermsSet(permsSet);
		}
		
		return info;

	}

	/**
	 * 认证(登录时调用)
	 * 登录信息和用户验证信息验证 
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken)authcToken;

        //查询用户信息
		SysUserEntity selectParam = new SysUserEntity();
		selectParam.setUsername(token.getUsername());
		SysUserEntity user =sysUserDao.selectOne(selectParam);
//        SysUserEntity user = sysUserDao.getByUserName(token.getUsername());
		SysUserEntity userx = sysUserService.getByPrimaryKey(1L);

		//账号不存在
        if(user == null) {
            throw new UnknownAccountException("账号或密码不正确");
        }
        if(user.getStatus() == 0){
        	throw new CustomException(Codes.FORBIDDEN.getCode(),Codes.FORBIDDEN.getMessage());
        }
        UserPrincipal principal = new UserPrincipal();
        principal.setUserId(user.getUserId());
        principal.setUsername(user.getUsername());
		principal.setNickname(user.getNickname());
		principal.setHeadImage(user.getHeadImage());
        principal.setStatus(user.getStatus());
        principal.setPermsLoad(false);
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName());
        return info;
	}
	
	
	//设置密码加密算法
	@Override
	public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
		HashedCredentialsMatcher shaCredentialsMatcher = new HashedCredentialsMatcher();
		shaCredentialsMatcher.setHashAlgorithmName(ShiroUtils.hashAlgorithmName);
		shaCredentialsMatcher.setHashIterations(ShiroUtils.hashIterations);
		super.setCredentialsMatcher(shaCredentialsMatcher);
	}

}
